home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 13288 / 13288.xpi / content / overlay.js < prev    next >
Text File  |  2010-01-24  |  62KB  |  1,393 lines

  1. var stmM = {
  2.     gPrefs: Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("extensions.stm."),
  3.     gFFContentAreaClick: null,    /* firefox original ContentAreaClick function */
  4.     TME_TOOLBARBUTTON: "stm-togglebutton",
  5.     gWinLoaded: false,
  6.     gBlockingOn: false,
  7.     gOldScrollBoxWidth: -1,
  8.     gFFVersion: Application.version.substr(0, 3),   //Firefox version, such as 3.5, 3.6   
  9.  
  10.     closeByKey: false,  //working with closeLeftTabs/closeRightTabs
  11.     openedTabs: new Array(),  //working with lastSelectedTab
  12.     arrayTop: 0,
  13.  
  14.     onLoad: function() {
  15.         this.addTabMenu();  // add tab context menu
  16.         this.changeHotkey("k.pageLock", this.gPrefs.getCharPref("pagelock.hotkey"));  // load hotkey
  17.         this.changeHotkey("k.block", this.gPrefs.getCharPref("block.hotkey"));  // load hotkey
  18.         this.changeHotkey("k.hideFF", this.gPrefs.getCharPref("bosskey.hidekey"));  // load hotkey
  19.         this.register();  // preference register
  20.         this.enableNewTabPosition();  //set tab parent and children
  21.         this.doEvalAtStart();   //execute removeBlankTab() in openUILinkIn()
  22.         //first run
  23.         this.openURLBarInNewTab(this.gPrefs.getBoolPref("openURLBarInNewTab"));
  24.         this.enableOpenBHSInNewTab(this.gPrefs.getBoolPref("openBHSInNewTab"));
  25.         this.chgTabBarPosition(this.gPrefs.getIntPref("tabBarPosition"));
  26.         this.chgNewTabBtnPos(this.gPrefs.getIntPref("newTabBtnPos"));
  27.         this.enableMultiTabRows(this.gPrefs.getBoolPref("tabBarMultiRows"));
  28.         this.showStatusbarIcon(this.gPrefs.getBoolPref("statusbarIcon"));
  29.         this.showToolMenuItem(this.gPrefs.getBoolPref("toolMenuItem"));
  30.         this.enableDoubleClickListener(this.gPrefs.getBoolPref("doubleClickRemoveTab"));
  31.         this.showCloseRightTabsMenu(this.gPrefs.getBoolPref("showCloseRightTabs"));
  32.         this.showCloseLeftTabsMenu(this.gPrefs.getBoolPref("showCloseLeftTabs"));
  33.         this.enableFocusAfterCloseTab(this.gPrefs.getIntPref("focusAfterCloseTab"));
  34.         this.showHistoryTopMenu(this.gPrefs.getBoolPref("showHistoryMenu"));
  35.         this.chgHistoryBtnShape(this.gPrefs.getIntPref("historyButtonShape"));
  36.         this.chgURLBarListFontSize(this.gPrefs.getIntPref("urlbarListFontSize"));
  37.         this.enablePL(this.gPrefs.getBoolPref("pagelock.enable"));
  38.         this.enableBlock(this.gPrefs.getBoolPref("block.enable"));
  39.         this.enableBosskey(this.gPrefs.getBoolPref("bosskey.enable"));
  40.         this.minimizeToSysTray(false, this.gPrefs.getBoolPref("minimizeAllToTray"));
  41.  
  42.         this.gWinLoaded = true;
  43.     },
  44.  
  45.     onUnLoad: function() {
  46.         this.unregister();
  47.     },
  48.  
  49.     register: function() {
  50.         var prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
  51.         this._branch = prefService.getBranch("extensions.stm.");
  52.         this._branch.QueryInterface(Components.interfaces.nsIPrefBranch2);
  53.         this._branch.addObserver("", this, false);
  54.     },
  55.  
  56.     unregister: function() {
  57.         if(!this._branch) return;
  58.         this._branch.removeObserver("", this);
  59.     },
  60.  
  61.     observe: function(aSubject, aTopic, aData) {
  62.         if(aTopic != "nsPref:changed") return;
  63.         switch (aData) {
  64.             case "openURLBarInNewTab":
  65.               this.openURLBarInNewTab(this.gPrefs.getBoolPref("openURLBarInNewTab"));
  66.               break;
  67.             case "openBHSInNewTab":
  68.               this.enableOpenBHSInNewTab(this.gPrefs.getBoolPref("openBHSInNewTab"));
  69.               break;
  70.             case "tabBarPosition":
  71.               this.chgTabBarPosition(this.gPrefs.getIntPref("tabBarPosition"));
  72.               break;
  73.             case "newTabBtnPos":
  74.               this.chgNewTabBtnPos(this.gPrefs.getIntPref("newTabBtnPos"));
  75.               break;
  76.             case "tabBarMultiRows":
  77.               this.enableMultiTabRows(this.gPrefs.getBoolPref("tabBarMultiRows"));
  78.               break;
  79.             case "statusbarIcon":
  80.               this.showStatusbarIcon(this.gPrefs.getBoolPref("statusbarIcon"));
  81.               break;
  82.             case "toolMenuItem":
  83.               this.showToolMenuItem(this.gPrefs.getBoolPref("toolMenuItem"));
  84.               break;
  85.             case "doubleClickRemoveTab":
  86.               this.enableDoubleClickListener(this.gPrefs.getBoolPref("doubleClickRemoveTab"));
  87.               break;
  88.             case "showCloseRightTabs":
  89.               this.showCloseRightTabsMenu(this.gPrefs.getBoolPref("showCloseRightTabs"));
  90.               break;
  91.             case "showCloseLeftTabs":
  92.               this.showCloseLeftTabsMenu(this.gPrefs.getBoolPref("showCloseLeftTabs"));
  93.               break;
  94.             case "focusAfterCloseTab":
  95.               this.enableFocusAfterCloseTab(this.gPrefs.getIntPref("focusAfterCloseTab"));
  96.               break;
  97.             case "showHistoryMenu":
  98.               this.showHistoryTopMenu(this.gPrefs.getBoolPref("showHistoryMenu"));
  99.               break;
  100.             case "historyButtonShape":
  101.               this.chgHistoryBtnShape(this.gPrefs.getIntPref("historyButtonShape"));
  102.               break;
  103.             case "urlbarListFontSize":
  104.               this.chgURLBarListFontSize(this.gPrefs.getIntPref("urlbarListFontSize"));
  105.               break;
  106.             case "pagelock.enable":
  107.               this.enablePL(this.gPrefs.getBoolPref("pagelock.enable"));
  108.               break;
  109.             case "pagelock.hotkey":
  110.               this.changeHotkey("k.pageLock", this.gPrefs.getCharPref("pagelock.hotkey"));
  111.               break;
  112.             case "pagelock.enableTabColor":
  113.             case "pagelock.enableTabTxtColor":
  114.             case "pagelock.tabColor":
  115.             case "pagelock.tabTxtColor":
  116.               this.changePLTabColor(true);
  117.               break;
  118.             case "pagelock.showTabMenu":
  119.               this.showPLTabMenu(this.gPrefs.getBoolPref("pagelock.showTabMenu"));
  120.               break;
  121.             case "pagelock.filter":
  122.               this.enableFilter(this.gPrefs.getBoolPref("pagelock.filter"));
  123.               break;
  124.             case "block.enable":
  125.               this.enableBlock(this.gPrefs.getBoolPref("block.enable"));
  126.               break;
  127.             case "block.hotkey":
  128.               this.changeHotkey("k.block", this.gPrefs.getCharPref("block.hotkey"));
  129.               break;
  130.             case "block.stopOnTabSwitch":
  131.               this.stopOnTabSwitch(this.gPrefs.getBoolPref("block.stopOnTabSwitch"));
  132.               break;
  133.             case "bosskey.enable":
  134.               this.enableBosskey(this.gPrefs.getBoolPref("bosskey.enable"));
  135.               break;
  136.             case "bosskey.hidekey":
  137.               this.changeHotkey("k.hideFF", this.gPrefs.getCharPref("bosskey.hidekey"));
  138.               break;
  139.             case "minimizeAllToTray":
  140.               this.minimizeToSysTray(true, this.gPrefs.getBoolPref("minimizeAllToTray"));
  141.               break;
  142.         }
  143.     },
  144.  
  145.     openURLBarInNewTab: function(penable) {
  146.         var urlbar = document.getElementById("urlbar");
  147.         if (penable)
  148.             eval("urlbar.handleCommand = " + urlbar.handleCommand.toString().replace(
  149.                 'if (aTriggeringEvent instanceof MouseEvent) {',
  150.                 'if (stmM.reloadedSelectedTab(url)) return; if (aTriggeringEvent) {'
  151.             ));
  152.         else
  153.             eval("urlbar.handleCommand = " + urlbar.handleCommand.toString().replace(
  154.                 'if (aTriggeringEvent) {',
  155.                 'if (aTriggeringEvent instanceof MouseEvent) {'
  156.             ).replace(
  157.                 'stmM.reloadedSelectedTab(url)',
  158.                 'false'
  159.             ));
  160.     },
  161.  
  162.     reloadedSelectedTab: function(url) {
  163.         document.getElementById("urlbar").handleRevert();
  164.         gBrowser.selectedBrowser.focus();
  165.         if (url == gBrowser.selectedBrowser.contentDocument.URL) {
  166.             gBrowser.selectedBrowser.reload();
  167.             return true;
  168.         } else 
  169.             return false;
  170.     },
  171.  
  172.     /* enable open bookmark/history/search in new tab */
  173.     enableOpenBHSInNewTab: function(penable) {
  174.         if (penable) {
  175.             eval("openUILinkIn = " + openUILinkIn.toString().replace(
  176.                 'switch (where)',
  177.                 'switch (stmC.onTabSwitch(url, where))'
  178.             ));
  179.             var sbar = document.getElementById("searchbar");
  180.             eval("sbar.handleSearchCommand = " + sbar.handleSearchCommand.toString().replace(
  181.                 'where = "tab";',
  182.                 'where = stmC.onTabSwitch("", "current");'
  183.             ));
  184.             eval("PlacesUIUtils._openTabset = " + PlacesUIUtils._openTabset.toString().replace(
  185.                 '(urls, loadInBackground, replaceCurrentTab);',
  186.                 '(urls, loadInBackground, false);'
  187.             ));
  188.         } else {
  189.             eval("openUILinkIn = " + openUILinkIn.toString().replace(
  190.                 'switch (stmC.onTabSwitch(url, where))',
  191.                 'switch (where)'
  192.             ));
  193.             var sbar = document.getElementById("searchbar");
  194.             eval("sbar.handleSearchCommand = " + sbar.handleSearchCommand.toString().replace(
  195.                 'where = stmC.onTabSwitch("", "current");',
  196.                 'where = "tab";'
  197.             ));
  198.             eval("PlacesUIUtils._openTabset = " + PlacesUIUtils._openTabset.toString().replace(
  199.                 '(urls, loadInBackground, false);',
  200.                 '(urls, loadInBackground, replaceCurrentTab);'
  201.             ));
  202.  
  203.         }
  204.     },
  205.  
  206.     doEvalAtStart: function() {
  207.         //execute removeBlankTab() in openUILinkIn()
  208.         eval("openUILinkIn = " + openUILinkIn.toString().replace(
  209.             'switch (',
  210.             'stmM.removeBlankTab(gBrowser.mCurrentTab); switch ('
  211.         ));
  212.  
  213.         eval("nsContextMenu.prototype.initMenu = " + nsContextMenu.prototype.initMenu.toString().replace(
  214.             'this.initItems();',
  215.             'this.initItems(); stmM.initMenuOfLoadSelect();'
  216.         ));
  217.  
  218.         var el = document.getAnonymousElementByAttribute(gBrowser, 'anonid', 'tabContextMenu');
  219.         el.setAttribute("onpopupshowing", "stmM.initTabContextMenu(); this.parentNode.parentNode.parentNode.updatePopupMenu(this);");
  220.  
  221.     },
  222.  
  223.     /* enable new tab position */
  224.     enableNewTabPosition: function() {
  225.         eval("gBrowser.addTab = " + gBrowser.addTab.toString().replace(
  226.             'return t;',
  227.             'return stmM.whereAddTab(t, aOwner, blank);'
  228.         ));
  229.     },
  230.  
  231.     /* Where to add New Tab */
  232.     whereAddTab: function(t, aOwner, blank) {
  233.         var func = this.whereAddTab.caller.caller.name;
  234.         if (!blank && func && ["_endRemoveTab","sss_restoreWindow","sss_undoCloseTab"].indexOf(func) == -1) 
  235.             this.removeBlankTab(t);
  236.         if (this.gPrefs.getBoolPref("newTabPosBackTabOnly"))
  237.             if (aOwner) return t;  // Do not handle bookmarks or history or search that open on foreground
  238.         var wtabs = gBrowser.tabContainer;
  239.         var s = gBrowser.selectedTab;
  240.         switch(this.gPrefs.getIntPref("newTabPosition")) {
  241.           case 1:  //right near current tab
  242.             if (wtabs.itemCount >= 2)
  243.                 gBrowser.moveTabTo(t, wtabs.selectedIndex + 1);
  244.           case 0:
  245.             if (!s.hasAttribute("stmTabMark"))
  246.                 s.setAttribute("stmTabMark", Math.random());
  247.             t.setAttribute("stmRightMark", s.getAttribute("stmTabMark"));
  248.             break;
  249.           case 2:  //right far from current tab
  250.             gBrowser.moveTabTo(t, wtabs.itemCount - 1);
  251.             if (s.hasAttribute("stmTabMark")) {
  252.                 var lindex;
  253.                 for (var i = wtabs.selectedIndex + 1; i < wtabs.itemCount; i++) {
  254.                     if (gBrowser.mTabs[i].getAttribute("stmRightMark") == s.getAttribute("stmTabMark")) lindex = i;
  255.                     else break;
  256.                 }
  257.                 if (lindex) 
  258.                     gBrowser.moveTabTo(t, lindex + 1);
  259.                 else 
  260.                     gBrowser.moveTabTo(t, wtabs.selectedIndex + 1);
  261.  
  262.             } else {
  263.                 s.setAttribute("stmTabMark", Math.random());
  264.                 if (wtabs.itemCount >= 2)
  265.                     gBrowser.moveTabTo(t, wtabs.selectedIndex + 1);
  266.             }
  267.             t.setAttribute("stmRightMark", s.getAttribute("stmTabMark"));
  268.             break;
  269.           case 3:   //rightest
  270.             if (wtabs.itemCount >= 2)
  271.                 gBrowser.moveTabTo(t, wtabs.itemCount);
  272.             if (!s.hasAttribute("stmTabMark"))
  273.                 s.setAttribute("stmTabMark", Math.random());
  274.             t.setAttribute("stmRightMark", s.getAttribute("stmTabMark"));
  275.             break;
  276.         }
  277.         return t;
  278.     },
  279.  
  280.     removeBlankTab: function(tab) {
  281.         if (!this.gPrefs.getBoolPref("openInBlankTab")) return;
  282.         for(var i = gBrowser.browsers.length - 1; i >= 0; i--) {
  283.             var t = gBrowser.mTabs[i];
  284.             if (t == tab) continue;
  285.             if (gBrowser.getBrowserAtIndex(i).currentURI.spec == 'about:blank' && !t.getAttribute("busy"))
  286.                 gBrowser.removeTab(t);
  287.         }
  288.     },
  289.  
  290.     /* change tab bar position */
  291.     chgTabBarPosition: function(pint) {
  292.         var position;
  293.         switch (pint) {
  294.             case 0:
  295.                 position = "";
  296.                 break;
  297.             case 1:    
  298.                 position = "-moz-box-direction: reverse;";
  299.                 break;
  300.         }
  301.         try    {
  302.             for(var i = 0; i < document.styleSheets.length; i++) {
  303.                 var ss = document.styleSheets[i];
  304.                 if(ss.href == "chrome://supertabmode/skin/stm.css")    {
  305.                     ss.deleteRule(3);
  306.                     ss.insertRule("#content > tabbox {" + position + "}", 3);
  307.                     break;
  308.                 }
  309.             }
  310.         }
  311.         catch(e){ alert("chgTabBarPosition error"); }
  312.     },
  313.  
  314.     chgNewTabBtnPos: function(pint) {
  315.         var i_nb = document.getAnonymousElementByAttribute(gBrowser.mTabContainer, 'anonid', 'arrowscrollbox')
  316.                                   .getElementsByAttribute('class', 'tabs-newtab-button')[0]
  317.         var r_nb = document.getAnonymousElementByAttribute(gBrowser.mTabContainer, 'anonid', 'newtab-button');
  318.         var button = gBrowser.mTabContainer.previousSibling;
  319.         switch (pint) {
  320.             case 0:  //default
  321.               if (button.getAttribute("class") == "stm-leftnewbutton") gBrowser.mStrip.removeChild(button);
  322.               i_nb.setAttribute('hidden', 'false');
  323.               r_nb.setAttribute('hidden', 'false');
  324.               var node = gBrowser.mStrip.lastChild;
  325.               gBrowser.mStrip.appendChild(node, node); //refresh
  326.               break;
  327.             case 1:  //left
  328.               if (button.getAttribute("class") != "stm-leftnewbutton") {
  329.                   var l_nb = i_nb.cloneNode(true);
  330.                   l_nb.setAttribute('class', 'stm-leftnewbutton');
  331.                   gBrowser.mStrip.insertBefore(l_nb, gBrowser.mTabContainer);
  332.               }
  333.               i_nb.setAttribute('hidden', 'true');
  334.               r_nb.setAttribute('hidden', 'true');
  335.               break;
  336.             case 2:  //hide
  337.               if (button.getAttribute("class") == "stm-leftnewbutton") gBrowser.mStrip.removeChild(button);
  338.               i_nb.setAttribute('hidden', 'true');
  339.               r_nb.setAttribute('hidden', 'false');
  340.               break;
  341.         }
  342.     },
  343.  
  344.     enableMultiTabRows: function(penable) {
  345.         if (penable) {
  346.             eval("gBrowser.moveTabTo = " + gBrowser.moveTabTo.toString().replace(
  347.                 'this.mTabContainer.mTabstrip.scrollBoxObject.ensureElementIsVisible(this.mCurrentTab);',
  348.                 'stmM.doNothing();'
  349.             ));
  350.             this.prepareMultiTabRows(true);
  351.             window.addEventListener("resize", this.toggleMultiTabRows, false);
  352.             this.toggleMultiTabRows("start");
  353.         } else {
  354.             eval("gBrowser.moveTabTo = " + gBrowser.moveTabTo.toString().replace(
  355.                 'stmM.doNothing();',
  356.                 'this.mTabContainer.mTabstrip.scrollBoxObject.ensureElementIsVisible(this.mCurrentTab);'
  357.             ));
  358.             this.prepareMultiTabRows(false);
  359.             window.removeEventListener("resize", this.toggleMultiTabRows, false);
  360.             this.toggleMultiTabRows("stop");
  361.         }
  362.     },
  363.  
  364.     prepareMultiTabRows: function(penable) {
  365.         var css = new Array();
  366.         css[8] = '.tabbrowser-arrowscrollbox > .scrollbutton-up, .tabbrowser-arrowscrollbox > .scrollbutton-down {' 
  367.                    + (penable?'display: none;':"") + '}';
  368.         css[9] = '.tabbrowser-arrowscrollbox > .tabs-newtab-button {' + (penable?'visibility: visible;':"") + '}';
  369.         css[10]= '.tabs-container > .tabs-newtab-button {' + (penable?'display: none;':"") + '}';
  370.         for(var i = 0; i < document.styleSheets.length; i++) {
  371.             var ss = document.styleSheets[i];
  372.             if(ss.href == "chrome://supertabmode/skin/stm.css")    {
  373.                 for (var j = 8; j <= 10; j++) {
  374.                     ss.deleteRule(j);
  375.                     ss.insertRule(css[j], j);
  376.                 }
  377.                 break;
  378.             }
  379.         }
  380.     },
  381.  
  382.     /* param: "start", "stop", event */
  383.     toggleMultiTabRows: function(e){
  384.         var newBtnWidth = 0;
  385.         switch (stmM.gPrefs.getIntPref("newTabBtnPos")) {
  386.             case 0:
  387.               newBtnWidth = 28; break;  // 28 comes from DOM Inspector
  388.             case 1:
  389.               newBtnWidth = 0; break;
  390.             case 2:
  391.               newBtnWidth = 0; break;
  392.         }
  393.         var barwidth = gBrowser.mTabContainer.mTabstrip.scrollBoxObject.width - newBtnWidth;
  394.         var tabwidth = gBrowser.mTabContainer.mTabMinWidth;
  395.         tabwidth = tabwidth < 32 ? 32:tabwidth;  //32 comes from calculated min width
  396.         var self = stmM.toggleMultiTabRows;
  397.         if (e == "start") {
  398.             if (tabwidth*(gBrowser.mTabs.length) <= barwidth || gBrowser.mTabs.length == 1) {
  399.                 gBrowser.tabContainer.addEventListener('TabOpen', self, false);
  400.                 return;
  401.             } else gBrowser.tabContainer.addEventListener('TabClose', self, false);
  402.         } else if (e == "stop") {
  403.             gBrowser.tabContainer.removeEventListener('TabOpen', self, false);
  404.             gBrowser.tabContainer.removeEventListener('TabClose', self, false);
  405.         } else if (e && e.type == "resize") {
  406.             if (stmM.gOldScrollBoxWidth != -1) {
  407.                 if (Math.abs(stmM.gOldScrollBoxWidth - barwidth) < 10) return;  //10 is randomly defined
  408.                 if (stmM.gOldScrollBoxWidth > barwidth) {  //smaller
  409.                     if (tabwidth*(gBrowser.mTabs.length) <= barwidth) {stmM.gOldScrollBoxWidth = barwidth; return;}
  410.                     stmM.doTabRowsListener('TabOpen');
  411.                     e = "start";
  412.                 } else if (stmM.gOldScrollBoxWidth < barwidth) {  //bigger
  413.                     if (tabwidth*(gBrowser.mTabs.length-1) > barwidth) {stmM.gOldScrollBoxWidth = barwidth; return;}
  414.                     stmM.doTabRowsListener('TabClose');
  415.                     e = "stop";
  416.                 }
  417.             }
  418.             stmM.gOldScrollBoxWidth = barwidth;
  419.         } else if (e && e.type == 'TabOpen') {
  420.             if (tabwidth*(gBrowser.mTabs.length) <= barwidth || gBrowser.mTabs.length == 1) return;
  421.             stmM.doTabRowsListener('TabOpen');
  422.         } else if (e && e.type == 'TabClose') {
  423.             if (tabwidth*(gBrowser.mTabs.length-1) > barwidth) return;
  424.             stmM.doTabRowsListener('TabClose');
  425.         }
  426.         var css = new Array();
  427.         css[4] = '.tabbrowser-arrowscrollbox > scrollbox > box {'
  428.                     + ((e == "start" || e.type == "TabOpen")?"display: block;":"") + '}';
  429.         css[5] = '.tabbrowser-arrowscrollbox > scrollbox {'
  430.                     + ((e == "start" || e.type == "TabOpen")?"overflow: visible;":"") + '}';
  431.         css[6] = '.tabbrowser-tab[selected="true"] {'
  432.                     + ((e == "start" || e.type == "TabOpen")?"padding: 2px 1px 2px 1px;border: 1px solid;border-bottom: none;":"") + '}';
  433.         css[7] = '.tabbrowser-tab {'
  434.                     + ((e == "start" || e.type == "TabOpen")?"padding: 2px 1px 1px 1px;border: 1px solid;border-bottom: none;":"") + '}';
  435.         for(var i = 0; i < document.styleSheets.length; i++) {
  436.             var ss = document.styleSheets[i];
  437.             if(ss.href == "chrome://supertabmode/skin/stm.css")    {
  438.                 for (var j = 4; j <= 7; j++) {
  439.                     ss.deleteRule(j);
  440.                     ss.insertRule(css[j], j);
  441.                 }
  442.                 break;
  443.             }
  444.         }
  445.     },
  446.  
  447.     doTabRowsListener: function(en) {
  448.         var c = gBrowser.tabContainer;
  449.         var t = stmM.toggleMultiTabRows;
  450.         c.removeEventListener(en=="TabOpen"?"TabOpen":"TabClose", t, false);
  451.         c.addEventListener(en=="TabOpen"?"TabClose":"TabOpen", t, false);
  452.     },
  453.  
  454.     /* enable double click listener */
  455.     enableDoubleClickListener: function(penable) {
  456.         var r = this.removeDoubleClickListener;
  457.         if (penable) {
  458.             gBrowser.mTabContainer.addEventListener('dblclick', this.onMouseDoubleClick, false);
  459.             window.addEventListener("unload", r, false);
  460.         } else {
  461.             this.removeDoubleClickListener();
  462.             window.removeEventListener("unload", r, false);
  463.         }
  464.     },
  465.  
  466.     /* remove double click listener */
  467.     removeDoubleClickListener: function(e) {
  468.         gBrowser.mTabContainer.removeEventListener('dblclick', this.onMouseDoubleClick, false); 
  469.     },
  470.  
  471.     /* double click to close a tab */
  472.     onMouseDoubleClick: function(e) {
  473.         if (e.target.localName == 'tab' && e.button == 0 && !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey && !e.getPreventDefault())
  474.             gBrowser.removeTab(e.target);
  475.     },
  476.  
  477.     enableFocusAfterCloseTab: function(position) {
  478.         if (position == 0) {
  479.             eval("gBrowser._endRemoveTab = " + gBrowser._endRemoveTab.toString().replace(
  480.                 'stmM.doNothing();',
  481.                 'this._blurTab(aTab);'
  482.             ).replace(
  483.                 'stmM.afterRemoveTab(aTab);',
  484.                 ''
  485.             ));
  486.             eval("gBrowser.removeAllTabsBut = " + gBrowser.removeAllTabsBut.toString().replace(
  487.                 'stmM.closeAllTabsBut(aTab);',
  488.                 'this.selectedTab = aTab;'
  489.             ));
  490.             eval("gBrowser.removeAllTabsBut = " + gBrowser.removeAllTabsBut.toString().replace(
  491.                 'return;',
  492.                 ''
  493.             ));
  494.         } else {
  495.             eval("gBrowser._endRemoveTab = " + gBrowser._endRemoveTab.toString().replace(
  496.                 'this._blurTab(aTab);',
  497.                 'stmM.doNothing();'
  498.             ).replace(
  499.                 'this.selectedTab._selected = true;',
  500.                 'stmM.afterRemoveTab(aTab);this.selectedTab._selected = true;'
  501.             ));
  502.             eval("gBrowser.removeAllTabsBut = " + gBrowser.removeAllTabsBut.toString().replace(
  503.                 'this.selectedTab = aTab;',
  504.                 'stmM.closeAllTabsBut(aTab); return;'
  505.             )); //make closeAllTabsBut() look smoothly.
  506.         }
  507.  
  508.         var c = gBrowser.tabContainer;
  509.         var l = this.setLastSelectedTab;
  510.         if (position == 7) c.addEventListener('select', l, false);
  511.         else c.removeEventListener('select', l, false);
  512.     },
  513.  
  514.     doNothing: function() {
  515.         return;
  516.     },
  517.  
  518.     setLastSelectedTab: function() {
  519.         var newtab = gBrowser.selectedTab;
  520.         if (stmM.arrayTop == 0) {
  521.             stmM.openedTabs[stmM.arrayTop++] = gBrowser.mTabs[0];
  522.         }
  523.         var finded = -1;
  524.         for (var i=0; i<stmM.arrayTop; i++) {
  525.             if (stmM.openedTabs[i] == newtab) {
  526.                 finded = i;
  527.                 break;
  528.             }
  529.         }
  530.         if (finded > -1) {
  531.             for (var i=finded; i<stmM.arrayTop-1; i++) {
  532.                 stmM.openedTabs[i] = stmM.openedTabs[i+1];
  533.             }
  534.             stmM.openedTabs[stmM.arrayTop-1] = newtab;
  535.         } else
  536.             stmM.openedTabs[stmM.arrayTop++] = newtab;
  537.     },
  538.  
  539.     afterRemoveTab: function(aTab) {
  540.         if (gBrowser.mCurrentTab != aTab) return;  //remove tab which is not selected
  541.  
  542.         var wStmRightMark = aTab.getAttribute("stmRightMark");
  543.         var wStmTabMark = aTab.getAttribute("stmTabMark");
  544.         var wIndex = aTab._tPos;
  545.         switch (this.gPrefs.getIntPref("focusAfterCloseTab")) {
  546.             case 1: //left
  547.               gBrowser.selectedTab = gBrowser.mTabs[wIndex-1>=0?wIndex-1:0];
  548.               return;
  549.               break;
  550.             case 2: //father, no father ->child first
  551.               if (!wStmRightMark) break;
  552.               var findex = this.getFatherTabIndex(wStmRightMark);
  553.               if (findex >= 0) {gBrowser.selectedTab = gBrowser.mTabs[findex]; return;}
  554.               for(var i = 0; i < gBrowser.mTabs.length; i++) {
  555.                   var ctab = gBrowser.mTabs[i];
  556.                   if (ctab.getAttribute("stmRightMark") == wStmRightMark) 
  557.                       {gBrowser.selectedTab = ctab; return;}
  558.               }
  559.               break;
  560.             case 3: //father right first, if no, father
  561.               if (!wStmRightMark) break;
  562.               var findex = this.getFatherTabIndex(wStmRightMark);
  563.               for(var i = (findex==-1?0:findex+1); i < gBrowser.mTabs.length; i++) {
  564.                   var ctab = gBrowser.mTabs[i];
  565.                   if (ctab.getAttribute("stmRightMark") == wStmRightMark)
  566.                       {gBrowser.selectedTab = ctab; return;}
  567.               }
  568.               if (findex >= 0) {gBrowser.selectedTab = gBrowser.mTabs[findex]; return;}
  569.               break;
  570.             case 4: //father right farest, if no, father
  571.               if (!wStmRightMark) break;
  572.               var findex = this.getFatherTabIndex(wStmRightMark);
  573.               var lchildtab;
  574.               for(var i = (findex==-1?0:findex+1); i < gBrowser.mTabs.length; i++) {
  575.                   var ctab = gBrowser.mTabs[i];
  576.                   if (ctab.getAttribute("stmRightMark") == wStmRightMark)
  577.                       lchildtab = ctab;
  578.               }
  579.               if (lchildtab) {gBrowser.selectedTab = lchildtab; return;}
  580.               if (findex >= 0) {gBrowser.selectedTab = gBrowser.mTabs[findex]; return;}
  581.               break;
  582.             case 5: //first
  583.               gBrowser.selectedTab = gBrowser.mTabs[0]; return;
  584.               break;
  585.             case 6: //last
  586.               gBrowser.selectedTab = gBrowser.mTabs[gBrowser.mTabs.length - 1]; return;
  587.               break;
  588.             case 7: //last selected tab
  589.               this.openedTabs[this.arrayTop-1] = null;
  590.               if (--this.arrayTop < 1) break;
  591.               gBrowser.selectedTab = this.openedTabs[this.arrayTop-1]; 
  592.               return;
  593.             case 8: //author's like
  594.               var cindex = this.findChildNotFather(wIndex, wStmRightMark);
  595.               if (cindex != -1) {gBrowser.selectedTab = gBrowser.mTabs[cindex]; return;}
  596.               if (!wStmTabMark) {
  597.                   var findex = this.getFatherTabIndex(wStmRightMark);
  598.                   if (findex != -1) {gBrowser.selectedTab = gBrowser.mTabs[findex]; return; }
  599.               }
  600.               cindex = this.findChildNotFather(wIndex);
  601.               if (cindex != -1) {gBrowser.selectedTab = gBrowser.mTabs[cindex]; return;}
  602.               break;
  603.         }
  604.         gBrowser.selectedTab = gBrowser.mTabs[wIndex==gBrowser.mTabs.length?wIndex-1:wIndex];  //default
  605.     },
  606.  
  607.     getFatherTabIndex: function(pstmmark) {
  608.         for(var i = 0; i < gBrowser.mTabs.length; i++) {
  609.             var ctab = gBrowser.mTabs[i];
  610.             if (ctab.getAttribute("stmTabMark") == pstmmark) return i;
  611.         }
  612.         return -1;
  613.     },
  614.  
  615.     //no 2nd param: find any child;  with 2nd param: find child with same father
  616.     findChildNotFather: function(pcindex, pstmmark) {
  617.         for(var i = pcindex; i < gBrowser.mTabs.length; i++) {
  618.             var ctab = gBrowser.mTabs[i];
  619.             if (!ctab.hasAttribute("stmTabMark")) {
  620.                 if (pstmmark) {if (pstmmark == ctab.getAttribute("stmRightMark")) return i;}
  621.                 else if (ctab.hasAttribute("stmRightMark")) return i;
  622.             }
  623.         }
  624.         for(var i = pcindex - 1; i >= 0; i--) {
  625.             var ctab = gBrowser.mTabs[i];
  626.             if (!ctab.hasAttribute("stmTabMark")) {
  627.                 if (pstmmark) {if (pstmmark == ctab.getAttribute("stmRightMark")) return i;}
  628.                 else if (ctab.hasAttribute("stmRightMark")) return i;
  629.             }
  630.         }
  631.         return -1;
  632.     },
  633.  
  634.     showHistoryTopMenu: function(pshow) {
  635.         document.getElementById("tabreopen-menu").setAttribute("hidden", !pshow);
  636.     },
  637.     
  638.     chgHistoryBtnShape: function(pshape) {
  639.         var e = document.getElementById("b.historybutton");
  640.         if (pshape == 0) {
  641.             e.setAttribute("oncommand", "document.getElementById('historybutton-popup').openPopup(this, 'after_start');");
  642.             e.setAttribute("type", "");
  643.         } else {
  644.             e.setAttribute("oncommand", "undoCloseTab();");
  645.             e.setAttribute("type", "menu-button");
  646.         }
  647.     },
  648.     
  649.     showHistoryMenuItems: function(menupopup) {
  650.       var undoPopup = menupopup;
  651.       // remove existing menu items
  652.       while (undoPopup.hasChildNodes())
  653.         undoPopup.removeChild(undoPopup.firstChild);
  654.  
  655.       // no restorable tabs, so return
  656.       if (HistoryMenu._ss.getClosedTabCount(window) == 0) {
  657.         var m = document.createElement("menuitem");
  658.         m.setAttribute("label", document.getElementById("stm.stringmanager").getString("history.empty"));
  659.         undoPopup.appendChild(m);
  660.         return;
  661.       }
  662.  
  663.       // populate menu
  664.       var undoItems = eval("(" + HistoryMenu._ss.getClosedTabData(window) + ")");
  665.       for (var i = 0; i < undoItems.length; i++) {
  666.         var m = document.createElement("menuitem");
  667.         m.setAttribute("label", undoItems[i].title);
  668.         if (undoItems[i].image) {
  669.           let iconURL = undoItems[i].image;
  670.           // don't initiate a connection just to fetch a favicon (see bug 467828)
  671.           if (/^https?:/.test(iconURL))
  672.             iconURL = "moz-anno:favicon:" + iconURL;
  673.           m.setAttribute("image", iconURL);
  674.         }
  675.         m.setAttribute("class", "menuitem-iconic bookmark-item");
  676.         m.setAttribute("value", i);
  677.         m.setAttribute("oncommand", "undoCloseTab(" + i + ");event.stopPropagation();");
  678.  
  679.         //firefox version
  680.         if (this.gFFVersion == "3.5")
  681.             m.addEventListener("click", undoCloseMiddleClick, false);
  682.         else
  683.             m.addEventListener("click", HistoryMenu._undoCloseMiddleClick, false);
  684.  
  685.         if (i == 0)
  686.           m.setAttribute("key", "key_undoCloseTab");
  687.         undoPopup.appendChild(m);
  688.       }
  689.       // "Open All in Tabs"
  690.       var strings = gNavigatorBundle;
  691.       undoPopup.appendChild(document.createElement("menuseparator"));
  692.       m = undoPopup.appendChild(document.createElement("menuitem"));
  693.  
  694.       //firefox version
  695.       if (this.gFFVersion == "3.5") {
  696.           m.setAttribute("label", strings.getString("menuOpenAllInTabs.label"));
  697.           m.setAttribute("accesskey", strings.getString("menuOpenAllInTabs.accesskey"));
  698.       } else {
  699.           m.id = "menu_restoreAllTabs";
  700.           m.setAttribute("label", strings.getString("menuRestoreAllTabs.label"));
  701.           m.setAttribute("accesskey", strings.getString("menuRestoreAllTabs.accesskey"));
  702.       }
  703.  
  704.       m.addEventListener("command", function() {
  705.         for (var i = 0; i < undoItems.length; i++)
  706.           undoCloseTab();
  707.       }, false);
  708.     },
  709.  
  710.     /* change urlbar list font size */
  711.     chgURLBarListFontSize: function(pint) {
  712.         var fontstyle, fontsize;
  713.         switch (pint) {
  714.             case 0: break;
  715.             case 1:    fontsize = "xx-small"; break;
  716.             case 2:    fontsize = "x-small";  break;
  717.             case 3:    fontsize = "small";    break;
  718.             case 4:    fontsize = "medium";   break;
  719.             case 5:    fontsize = "large";    break;
  720.             case 6:    fontsize = "x-large";  break;
  721.             case 7:    fontsize = "x-large";  break;
  722.         }
  723.         if (pint == 0)
  724.             fontstyle = "";
  725.         else
  726.             fontstyle = "font-size: " + fontsize + " !important;";
  727.         try    {
  728.             for(var i = 0; i < document.styleSheets.length; i++) {
  729.                 var ss = document.styleSheets[i];
  730.                 if(ss.href == "chrome://supertabmode/skin/stm.css")    {
  731.                     ss.deleteRule(2);
  732.                     ss.insertRule(".ac-comment {" + fontstyle + "}", 2);
  733.                     break;
  734.                 }
  735.             }
  736.         }
  737.         catch(e){ alert("chgURLBarListFontSize error"); }
  738.     },
  739.  
  740.     /* load selected text in a new tab */
  741.     loadSelectInTab: function() {
  742.         var w = document.commandDispatcher.focusedWindow;
  743.         var s = stmC.trim(w.getSelection().toString());
  744.         if (s.substr(0, 4).toUpperCase() != "HTTP")
  745.             s = "http://" + s;
  746.         openNewTabWith(s, gBrowser.contentDocument);
  747.     },
  748.  
  749.     /* init menu of loading selected text in a new tab */
  750.     initMenuOfLoadSelect: function() {
  751.         if (!this.gPrefs.getBoolPref("showLoadSelectMenu")) {
  752.             document.getElementById("stm.context-loadselect").hidden = true;
  753.             return;
  754.         }
  755.  
  756.         var s = getBrowserSelection(15);
  757.         if (s.indexOf(".") >= 0) {
  758.             if (getBrowserSelection().length > s.length)
  759.                 s += "...";
  760.             var sb = document.getElementById("stm.stringmanager");
  761.             s = sb.getString("loadselectmenu.label") + ' "' + s + '"';
  762.             document.getElementById("stm.context-loadselect").label = s;
  763.             document.getElementById("stm.context-loadselect").hidden = false;
  764.         } else {
  765.             document.getElementById("stm.context-loadselect").hidden = true;
  766.         }
  767.     },
  768.  
  769.     /* show/hide tool menu item */
  770.     showToolMenuItem: function(pshow) {
  771.         document.getElementById("stm.menuitem").setAttribute("hidden", !pshow);
  772.     },
  773.  
  774.     /* open preference window from tool menu*/
  775.     openPrefDialog: function() {
  776.         const prefURL = "chrome://supertabmode/content/preference.xul";
  777.         var features = "chrome,titlebar,toolbar,centerscreen,modal";
  778.         window.openDialog(prefURL, "", features);
  779.     },
  780.  
  781.     /* enable pagelock */
  782.     enablePL: function(penable) {
  783.         if (penable) {
  784.             this.gFFContentAreaClick = window.contentAreaClick;
  785.             window.contentAreaClick = this.patchedContentAreaClick;
  786.             this.enablePLHotKey(true);
  787.             this.enablePLMouseKey(true);
  788.             this.changePLTabColor(true);
  789.             this.showPLTabMenu(this.gPrefs.getBoolPref("pagelock.showTabMenu"));
  790.             this.showPLStatusbarMenu(this.gPrefs.getBoolPref("pagelock.showStatusbarMenu"));
  791.             if (this.gWinLoaded) this.toggleToolbarButton(TME_TOOLBARBUTTON, true);
  792.             this.enableFilter(this.gPrefs.getBoolPref("pagelock.filter"));
  793.         } else {
  794.             if (this.gFFContentAreaClick) window.contentAreaClick = this.gFFContentAreaClick;
  795.             this.enablePLHotKey(false);
  796.             this.enablePLMouseKey(false);
  797.             this.changePLTabColor(false);
  798.             this.showPLTabMenu(false);
  799.             this.showPLStatusbarMenu(false);
  800.             if (this.gWinLoaded) this.toggleToolbarButton(TME_TOOLBARBUTTON, false);
  801.             this.enableFilter(false);
  802.         }
  803.     },
  804.  
  805.     /* patched firefox ContentAreaClick function (pagelock) */
  806.     patchedContentAreaClick: function(e, fieldNormalClicks) {
  807.         if (gBrowser.selectedTab.getAttribute("isPageLocked") == "true"
  808.             && (e.target.localName.toUpperCase() == "A" || e.target.parentNode.localName.toUpperCase() == "A"))
  809.             if(e.button == 0 && !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey && !e.getPreventDefault()) {
  810.                 var newEvent = document.createEvent("MouseEvents");
  811.                 newEvent.initMouseEvent("click", e.bubbles, e.cancelable, e.view, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, true, e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget); 
  812.                 e.preventDefault();
  813.                 e.stopPropagation();
  814.                 e.target.dispatchEvent(newEvent);
  815.                 return;
  816.             }
  817.         stmM.gFFContentAreaClick(e, fieldNormalClicks);
  818.         return;
  819.     },
  820.  
  821.     /* enable pagelock toggle keypress */
  822.     enablePLHotKey: function(penable) {
  823.         if (penable)
  824.             document.getElementById("k.pageLock").setAttribute("disabled", false);
  825.         else
  826.             document.getElementById("k.pageLock").setAttribute("disabled", true);
  827.     },
  828.  
  829.     /* enable pagelock toggle mouse listener */
  830.     enablePLMouseKey: function(penable) {
  831.         var r = this.removeMouseKeyListener;
  832.         if (penable) {
  833.             gBrowser.mTabContainer.addEventListener('click', this.onPLMouseKey, false);
  834.             window.addEventListener("unload", r, false);
  835.         } else {
  836.             this.removeMouseKeyListener();
  837.             window.removeEventListener("unload", r, false);
  838.         }
  839.  
  840.     },
  841.  
  842.     /* remove pagelock mouse key listener */
  843.     removeMouseKeyListener: function(e) {
  844.         gBrowser.mTabContainer.removeEventListener('click', this.onPLMouseKey, false);
  845.     },
  846.  
  847.     /* mouse key to toggle pagelock */
  848.     onPLMouseKey: function(e) {
  849.         switch(stmM.gPrefs.getIntPref("pagelock.mousekey"))
  850.         {
  851.           case 0:    /* ctrl key */
  852.               if(e.altKey || !e.ctrlKey || e.shiftKey || e.metaKey || e.button != 0 || e.getPreventDefault())
  853.                   return;
  854.               break;
  855.           case 1:    /* shift key */
  856.               if(e.altKey || e.ctrlKey || !e.shiftKey || e.metaKey || e.button != 0 || e.getPreventDefault())
  857.                   return;
  858.               break;
  859.           default:  // Error
  860.               alert("unknown error: swich to default!");
  861.               return;
  862.         }
  863.  
  864.         stmM.togglePL();
  865.     },
  866.  
  867.     /* toggle pagelock */
  868.     togglePL: function() {
  869.         var url = gBrowser.selectedBrowser.contentDocument.URL;
  870.         if (url == "about:blank") return;
  871.  
  872.         var t = gBrowser.selectedTab;
  873.         if (t.getAttribute("isPageLocked") == "true") {
  874.             t.removeAttribute("isPageLocked");
  875.         }
  876.         else {
  877.             t.setAttribute("isPageLocked", "true");
  878.         }
  879.     },
  880.  
  881.     changeHotkey: function(pename, photkey) {
  882.         var list = photkey.split("|:|")[1].split("[+]");
  883.         var mykey = document.getElementById(pename);
  884.         mykey.removeAttribute("keycode");
  885.         mykey.removeAttribute("key");
  886.         mykey.removeAttribute("modifiers");
  887.         if (list[0]) mykey.setAttribute("keycode", list[0]);
  888.         if (list[1]) mykey.setAttribute("key", list[1]);
  889.         if (list[2]) mykey.setAttribute("modifiers", list[2]);
  890.         //try to invalidate cache
  891.         var keyset = mykey.parentNode;
  892.         keyset.parentNode.insertBefore(keyset, keyset.nextSibling);
  893.     },
  894.  
  895.     /* change pagelock tab color */
  896.     changePLTabColor: function(penable) {
  897.         var bkcolorrule, txtcolorrule;
  898.         if (penable) {
  899.             var enable = this.gPrefs.getBoolPref("pagelock.enableTabColor");
  900.             var color = this.gPrefs.getCharPref("pagelock.tabColor");
  901.             bkcolorrule = enable==true?("background-color: " + color + " !important;") : "";
  902.  
  903.             enable = this.gPrefs.getBoolPref("pagelock.enableTabTxtColor");
  904.             color = this.gPrefs.getCharPref("pagelock.tabTxtColor");
  905.             txtcolorrule = enable==true?("color: " + color + " !important;")    : "";
  906.         } else {
  907.             colorrule = "";
  908.             textcolorrule = "";
  909.         }
  910.  
  911.         try    {
  912.             for(var i = 0; i < document.styleSheets.length; i++) {
  913.                 var ss = document.styleSheets[i];
  914.                 if(ss.href == "chrome://supertabmode/skin/stm.css") {
  915.                     ss.deleteRule(1);
  916.                     ss.insertRule("#browser tab.tabbrowser-tab[isPageLocked=true] {" + bkcolorrule + txtcolorrule + "}", 1);
  917.                     break;
  918.                 }
  919.             }
  920.         }
  921.         catch(e){ alert("coloratePageLockTab error"); }
  922.     },
  923.  
  924.     /* add Tab context menu */
  925.     addTabMenu: function() {
  926.         var m = gBrowser.mStrip.firstChild.nextSibling;
  927.         var f = m.firstChild;
  928.         if (f) {
  929.             for (var i=0; i<=2; i++) 
  930.                 m.insertBefore(document.getElementById("stm.tabBlockScope" + i), f);
  931.             m.insertBefore(document.getElementById("stm.tmSepa2"), f);
  932.             m.insertBefore(document.getElementById("stm.tabBlockStopOnTabSwitch"), f);
  933.             m.insertBefore(document.getElementById("stm.tmSepa1"), f);
  934.             for (var i=0; i<=2; i++) 
  935.                 m.insertBefore(document.getElementById("stm.tabpagelock" + i), f);
  936.             m.insertBefore(document.getElementById("stm.tmSepa0"), f);
  937.         }
  938.         var cm = document.getElementById("context_closeOtherTabs");
  939.         if (cm) {
  940.             m.insertBefore(document.getElementById("stm.tCloseRTabs"), cm);
  941.             m.insertBefore(document.getElementById("stm.tCloseLTabs"), cm);
  942.         }
  943.     },
  944.  
  945.     initTabContextMenu: function() {
  946.         var b = this.gPrefs.getBoolPref("block.enable") && this.gPrefs.getBoolPref("block.showTabMenu");
  947.         this.showBlockTabMenu(b);
  948.         if (!b) return;
  949.  
  950.         document.getElementById("stm.tabBlockStopOnTabSwitch").setAttribute("checked", this.gPrefs.getBoolPref("block.stopOnTabSwitch"));
  951.         for (var i=0; i<=2; i++) {
  952.             document.getElementById("stm.tabBlockScope" + i).setAttribute("checked", (this.gPrefs.getIntPref("block.blockScope") == i && this.gBlockingOn));
  953.         }
  954.     },
  955.  
  956.     /* show/hide tab context pagelock menu */
  957.     showPLTabMenu: function(penable) {
  958.         for (var i=0; i<=2; i++) 
  959.             document.getElementById("stm.tabpagelock" + i).setAttribute("hidden", !penable);
  960.         document.getElementById("stm.tmSepa0").setAttribute("hidden", !penable);
  961.     },
  962.  
  963.     /* show/hide tab context Close right tabs menu */
  964.     showCloseRightTabsMenu: function(penable) {
  965.         document.getElementById("stm.tCloseRTabs").setAttribute("hidden", !penable);
  966.     },
  967.  
  968.     /* show/hide tab context Close left tabs menu */
  969.     showCloseLeftTabsMenu: function(penable) {
  970.         document.getElementById("stm.tCloseLTabs").setAttribute("hidden", !penable);
  971.     },
  972.  
  973.     /* close right tabs */
  974.     closeRightTabs: function() {
  975.         this.enableFocusAfterCloseTab(0);  //make closing look smoothly
  976.         var aTab;
  977.         if (this.closeByKey) 
  978.             aTab = gBrowser.selectedTab;
  979.         else
  980.             aTab = gBrowser.mContextTab;
  981.         gBrowser.selectedTab = aTab;
  982.         for (let i = gBrowser.mTabs.length - 1; i > aTab._tPos; --i) {
  983.             gBrowser.removeTab(gBrowser.mTabs[i]);
  984.         }
  985.         gBrowser.selectedTab = aTab;
  986.         this.enableFocusAfterCloseTab(this.gPrefs.getIntPref("focusAfterCloseTab"));
  987.         this.closeByKey = false; 
  988.     },
  989.  
  990.     /* close left tabs */
  991.     closeLeftTabs: function() {
  992.         this.enableFocusAfterCloseTab(0);  //make closing look smoothly
  993.         var aTab;
  994.         if (this.closeByKey) 
  995.             aTab = gBrowser.selectedTab;
  996.         else
  997.             aTab = gBrowser.mContextTab;
  998.         gBrowser.selectedTab = aTab;
  999.         for(var i = aTab._tPos - 1; i >= 0; i--) {
  1000.             gBrowser.removeTab(gBrowser.mTabs[i]);
  1001.         }
  1002.         gBrowser.selectedTab = aTab;
  1003.         this.enableFocusAfterCloseTab(this.gPrefs.getIntPref("focusAfterCloseTab"));
  1004.         this.closeByKey = false; 
  1005.     },
  1006.  
  1007.     closeAllTabsBut: function(aTab) {
  1008.         if (this.gPrefs.getIntPref("focusAfterCloseTab") != 0 )
  1009.             eval("gBrowser._endRemoveTab = " + gBrowser._endRemoveTab.toString().replace(
  1010.                 'stmM.doNothing();',
  1011.                 'this._blurTab(aTab);'
  1012.             ).replace(
  1013.                 'stmM.afterRemoveTab(aTab);',
  1014.                 ''
  1015.             ));
  1016.         gBrowser.selectedTab = aTab;
  1017.         for (let i = gBrowser.mTabs.length - 1; i >= 0; --i) {
  1018.         if (gBrowser.mTabs[i] != aTab)
  1019.             gBrowser.removeTab(gBrowser.mTabs[i]);
  1020.         }
  1021.  
  1022.         if (this.gPrefs.getIntPref("focusAfterCloseTab") != 0 )
  1023.             eval("gBrowser._endRemoveTab = " + gBrowser._endRemoveTab.toString().replace(
  1024.                 'this._blurTab(aTab);',
  1025.                 'stmM.doNothing();'
  1026.             ).replace(
  1027.                 'this.selectedTab._selected = true;',
  1028.                 'stmM.afterRemoveTab(aTab);this.selectedTab._selected = true;'
  1029.             ));
  1030.     },
  1031.  
  1032.     showPLStatusbarMenu: function(penable) {
  1033.         document.getElementById("stm.managelist").setAttribute("hidden", !penable);
  1034.         document.getElementById("stm.keeppagelocked").setAttribute("hidden", !penable);
  1035.         document.getElementById("stm.smSepa0").setAttribute("hidden", !penable);
  1036.     },
  1037.  
  1038.     /* toggle toolbar button. true:show, false:hide, no parameter:toggle */
  1039.     toggleToolbarButton: function(bname, penable) {
  1040.         var navbar = document.getElementById("nav-bar");
  1041.         var curSet = navbar.currentSet;
  1042.         var set;
  1043.         if (curSet.indexOf(bname) == -1) {
  1044.             if (penable == false) return;
  1045.             // Place the button before the urlbar
  1046.             if (curSet.indexOf("urlbar-container") != -1)
  1047.                 set = curSet.replace(/urlbar-container/, bname + ",urlbar-container");
  1048.             else  // at the end
  1049.                 set = curSet + "," + bname;
  1050.         } else {
  1051.             if (penable == true) return;
  1052.             if (curSet.indexOf(bname)==0)    //toolbutton is at the most left
  1053.                 set = curSet.replace(bname + "," , "");
  1054.             else
  1055.                 set = curSet.replace("," + bname, "");
  1056.         }
  1057.         navbar.setAttribute("currentset", set);
  1058.         navbar.currentSet = set;
  1059.         document.persist("nav-bar", "currentset");
  1060.         // If you don't do the following call, funny things happen
  1061.         //try { BrowserToolboxCustomizeDone(true); } catch (e) { }
  1062.     },
  1063.  
  1064.     /* toolbar button click */
  1065.     onToolbarButtonClick: function(e) {
  1066.         if (!this.gPrefs.getBoolPref("pagelock.enable")){
  1067.             var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
  1068.             var sb = document.getElementById("stm.stringmanager");
  1069.             if (prompts.confirm(null, sb.getString("pagelockdisabled.title"), sb.getString("pagelockdisabled")))
  1070.                 this.gPrefs.setBoolPref("pagelock.enable", true);
  1071.             else
  1072.                 return;
  1073.         }
  1074.         this.togglePL();
  1075.     },
  1076.  
  1077.     /* pagelock tab Menu click */
  1078.     onTabMenuPageLockClick: function(e) {
  1079.         gBrowser.selectedTab = gBrowser.mContextTab;
  1080.         this.togglePL();
  1081.     },
  1082.  
  1083.     /* toggle statusbar icon */
  1084.     showStatusbarIcon: function(pshow) {
  1085.         document.getElementById("stm.statuspanel").setAttribute("hidden", !pshow);
  1086.     },
  1087.  
  1088.     /* statusbar icon click */
  1089.     onStatusbarIconClick: function(e) {
  1090.         switch(e.button) {
  1091.             case 0:
  1092.                 if (!this.gPrefs.getBoolPref("pagelock.enable")){
  1093.                     var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
  1094.                     var sb = document.getElementById("stm.stringmanager");
  1095.                     if (prompts.confirm(null, sb.getString("pagelockdisabled.title"), sb.getString("pagelockdisabled")))
  1096.                         this.gPrefs.setBoolPref("pagelock.enable", true);
  1097.                     else
  1098.                         return;
  1099.                 }
  1100.                 this.togglePL();
  1101.                 break;
  1102.             case 1:
  1103.                 if (!this.gPrefs.getBoolPref("block.enable")){
  1104.                     var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
  1105.                     var sb = document.getElementById("stm.stringmanager");
  1106.                     if (prompts.confirm(null, sb.getString("blockdisabled.title"), sb.getString("blockdisabled")))
  1107.                         this.gPrefs.setBoolPref("block.enable", true);
  1108.                     else
  1109.                         return;
  1110.                 }
  1111.                 this.toggleBlock();
  1112.                 break;
  1113.             case 2:
  1114.                 var b = this.gPrefs.getBoolPref("block.enable") && this.gPrefs.getBoolPref("block.showStatusbarMenu");
  1115.                 this.showBlockStatusbarMenu(b);
  1116.                 b = this.gPrefs.getBoolPref("pagelock.enable") && this.gPrefs.getBoolPref("pagelock.showStatusbarMenu");
  1117.                 this.showPLStatusbarMenu(b);
  1118.  
  1119.                 document.getElementById("stm.popup").openPopup(e.target, "before_start");
  1120.                 break;
  1121.         }
  1122.     },
  1123.  
  1124.     /* click exit at statusbar icon right-click menu*/
  1125.     onExitStatusbarIcon: function() {
  1126.         this.gPrefs.setBoolPref("statusbarIcon", false);
  1127.     },
  1128.  
  1129.     onTabMenuAddIntoListClick: function() {
  1130.         gBrowser.selectedTab = gBrowser.mContextTab;
  1131.         this.addIntoList();
  1132.     },
  1133.  
  1134.     /* add into auto-pagelock url list*/
  1135.     addIntoList: function(e) {
  1136.         gBrowser.selectedTab = gBrowser.mContextTab;
  1137.         var rule = gBrowser.currentURI.spec;
  1138.         var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
  1139.         var sb = document.getElementById("stm.stringmanager");
  1140.         if (!prompts.confirm(null, null, sb.getString("urlInsertPrompt") + "\n\n" + gBrowser.currentURI.spec + "\n ")) return;
  1141.         if (rule != "" && rule != "about:blank") {
  1142.             if (rule.indexOf("://") < 0) {
  1143.                 rule = (/^[A-Za-z]:/.test(rule) ? "file:///"+rule.replace(/\\/g,"/") : "http://"+rule+"/");
  1144.                 if (/^file:\/\/.*/.test(rule)) rule = encodeURI(rule);
  1145.             }
  1146.             rule = rule.replace(/\s/g, "%20");
  1147.  
  1148.             var s = this.gPrefs.getComplexValue("pagelock.filterlist", Components.interfaces.nsISupportsString).data;
  1149.             var list = (s ? s.split(" ") : "");
  1150.  
  1151.             for (var i = 0; i < list.length; i++) {
  1152.                 var item = list[i].split("\b");
  1153.                 if (item[0] == rule){
  1154.                     prompts.alert(null, null, sb.getString("urlInsertError"));
  1155.                     return;
  1156.                 }
  1157.             }
  1158.             var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
  1159.             str.data = s + " " + rule;
  1160.             this.gPrefs.setComplexValue("pagelock.filterlist", Components.interfaces.nsISupportsString, str);
  1161.             gBrowser.selectedTab.setAttribute("isPageLocked", "true");
  1162.         }
  1163.     },
  1164.  
  1165.     /* enable or disable page lock filter */
  1166.     enableFilter: function(penable) {
  1167.         var r = this.removeFilterListener;
  1168.         if (penable) {
  1169.             gBrowser.addTabsProgressListener(this.newPageListener);
  1170.             window.addEventListener("unload", r, false);
  1171.         } else {
  1172.             this.removeFilterListener();
  1173.             window.removeEventListener("unload", r, false);
  1174.         }    
  1175.     },
  1176.  
  1177.     /* remove pagelock filter listener */
  1178.     removeFilterListener: function() {
  1179.         gBrowser.removeTabsProgressListener(this.newPageListener);
  1180.     },
  1181.  
  1182.     /* new page loading listener */
  1183.     newPageListener: {
  1184.         onLocationChange: function(aBrowser, aWebProgress, aRequest, aLocationURI) {
  1185.             var newurl = aLocationURI.spec;
  1186.             if (newurl.indexOf("://") < 0)  return;
  1187.  
  1188.             var s = stmM.gPrefs.getComplexValue("pagelock.filterlist", Components.interfaces.nsISupportsString).data;
  1189.             var list = (s ? s.split(" ") : "");
  1190.             var finded = false;
  1191.             for (var i = 0; i < list.length; i++) {
  1192.                 var item = list[i].split("\b");
  1193.                 if (item.length == 1) {  //enabled
  1194.                     if (item[0] == newurl) { finded = true; break; }
  1195.                 }
  1196.             }
  1197.             var wtab = gBrowser.mTabs[gBrowser.getBrowserIndexForDocument(aBrowser.contentDocument)];
  1198.             if (finded) wtab.setAttribute("isPageLocked", "true"); 
  1199.             else wtab.removeAttribute("isPageLocked"); 
  1200.         },
  1201.  
  1202.         onStateChange: function(aWebProgress, aRequest, aFlag, aStatus) { },
  1203.         onProgressChange: function(aWebProgress, aRequest, curSelf, maxSelf, curTot, maxTot) { },
  1204.         onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) { },
  1205.         onSecurityChange: function(aWebProgress, aRequest, aState) { }
  1206.  
  1207.     },
  1208.  
  1209.     /* enable block */
  1210.     enableBlock: function(penable) {
  1211.         if (penable) {
  1212.             this.enableBlockHotKey(true);
  1213.             this.showBlockTabMenu(this.gPrefs.getBoolPref("block.showTabMenu"));
  1214.             this.showBlockStatusbarMenu(this.gPrefs.getBoolPref("block.showStatusbarMenu"));
  1215.         } else {
  1216.             this.enableBlockHotKey(false);
  1217.             this.showBlockTabMenu(false);
  1218.             this.showBlockStatusbarMenu(false);
  1219.             if (this.gBlockingOn) this.disableBlockObserver();
  1220.         }
  1221.     },
  1222.  
  1223.     enableBlockHotKey: function(penable) {
  1224.         var e = document.getElementById("k.block");
  1225.         if (penable)
  1226.             e.setAttribute("disabled", false);
  1227.         else
  1228.             e.setAttribute("disabled", true);
  1229.     },
  1230.  
  1231.     stopOnTabSwitch: function(penable) {
  1232.         var c = gBrowser.tabContainer;
  1233.         var f = this.disableBlockObserver;
  1234.         if (penable) 
  1235.             c.addEventListener("TabSelect", f, false);
  1236.         else 
  1237.             c.removeEventListener("TabSelect", f, false);
  1238.     },
  1239.  
  1240.     /* show/hide tab context block menu */
  1241.     showBlockTabMenu: function(penable) {
  1242.         for (var i=0; i<=2; i++)
  1243.             document.getElementById("stm.tabBlockScope" + i).setAttribute("hidden", !penable);
  1244.         document.getElementById("stm.tmSepa2").setAttribute("hidden", !penable);
  1245.         document.getElementById("stm.tabBlockStopOnTabSwitch").setAttribute("hidden", !penable);
  1246.         document.getElementById("stm.tmSepa1").setAttribute("hidden", !penable);
  1247.     },
  1248.  
  1249.     showBlockStatusbarMenu: function(penable) {
  1250.         document.getElementById("stm.blockOption").setAttribute("hidden", !penable);
  1251.         document.getElementById("stm.smSepa2").setAttribute("hidden", !penable);
  1252.         for (var i=0; i<=2; i++) document.getElementById("stm.blockScope" + i).setAttribute("hidden", !penable);
  1253.         document.getElementById("stm.smSepa1").setAttribute("hidden", !penable);
  1254.         
  1255.         if (penable) {
  1256.             document.getElementById("stm.blockOption").setAttribute("checked", this.gPrefs.getBoolPref("block.stopOnTabSwitch"));
  1257.             for (var i=0; i<=2; i++) {
  1258.                 document.getElementById("stm.blockScope" + i).setAttribute("checked", (this.gPrefs.getIntPref("block.blockScope") == i && this.gBlockingOn));
  1259.             }
  1260.         }
  1261.     },
  1262.  
  1263.     blockObserver: {
  1264.         observe: function(aSubject, aTopic, aData) {
  1265.             aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);
  1266.             var url = aSubject.URI.spec;
  1267.             var aBrowser = this.getBrowserfromDOM(aSubject, aSubject);
  1268.             if (stmM.gPrefs.getBoolPref("block.stopOnTabSwitch")) {
  1269.                 if (this.noCancel(url, aSubject.URI.host, gBrowser.currentURI.host)) return;  //request is in scope, do not block
  1270.                 if (!aBrowser || aBrowser != gBrowser.selectedBrowser) return;
  1271.             } else {
  1272.                 for (var i = 0; i < gBrowser.browsers.length; i++) {
  1273.                     if (this.noCancel(url, aSubject.URI.host, gBrowser.getBrowserAtIndex(i).currentURI.host)) return;
  1274.                 }
  1275.                 if (!aBrowser || !aBrowser.contentTitle) return; //new tab first request has no contentTitle
  1276.             }
  1277.             aSubject.cancel(Components.results.NS_ERROR_FAILURE);
  1278.         },
  1279.  
  1280.         noCancel: function(url, httphost, chost) {
  1281.             switch(stmM.gPrefs.getIntPref("block.blockScope")) {
  1282.                 case 0:  //not host
  1283.                   if (httphost == chost) return true;
  1284.                   break;
  1285.                 case 1:  //pics
  1286.                   if (!this.isType(url, 1))  return true;
  1287.                   break;
  1288.                 case 2:  //music
  1289.                   if (!this.isType(url, 2))  return true;
  1290.                   break;
  1291.             }
  1292.             return false;
  1293.         },
  1294.  
  1295.         isType: function(url, type) {
  1296.             var exts;
  1297.             if (type == 1) 
  1298.                 exts = new Array("js", "gif", "jpg", "jpeg", "png", "swf", "svg", "bmp");
  1299.             else if (type == 2) 
  1300.                 exts = new Array("mp3", "wma", "wav", "rm", "asf", "avi", "mpg", "mpeg", "mid", "wmv", "asx", "ra", "ram");
  1301.             for (var i in exts) {
  1302.                 if (url.toLowerCase().indexOf("." + exts[i]) > -1) 
  1303.                     return true;
  1304.             }
  1305.             return false;
  1306.         },
  1307.  
  1308.         getBrowserfromDOM: function(aChannel, aSubject) {
  1309.             try {
  1310.                 var notificationCallbacks = aChannel.notificationCallbacks ? aChannel.notificationCallbacks : aSubject.loadGroup.notificationCallbacks;
  1311.                 if (!notificationCallbacks) return null;
  1312.                 var callback = notificationCallbacks.getInterface(Components.interfaces.nsIDOMWindow);
  1313.                 return callback.top.document ? gBrowser.getBrowserForDocument(callback.top.document) : null;
  1314.             }
  1315.             catch(e) { dump(e + "\n"); return null; }
  1316.         },
  1317.     },
  1318.  
  1319.     toggleBlock: function() {
  1320.         gBrowser.selectedBrowser.stop();
  1321.         if (!this.gBlockingOn)
  1322.             this.enableBlockObserver();
  1323.         else
  1324.             this.disableBlockObserver();
  1325.         gBrowser.selectedBrowser.reloadWithFlags(Components.interfaces.nsIRequest.LOAD_NORMAL);
  1326.     },
  1327.  
  1328.     enableBlockObserver: function() {
  1329.         Components.classes['@mozilla.org/observer-service;1'].getService(Components.interfaces.nsIObserverService).addObserver(this.blockObserver, 'http-on-modify-request', false);
  1330.         if (this.gPrefs.getBoolPref("block.stopOnTabSwitch"))
  1331.             gBrowser.tabContainer.addEventListener("TabSelect", this.disableBlockObserver, false);
  1332.         this.gBlockingOn = true;
  1333.         document.getElementById("stm.statuspanel").image="chrome://supertabmode/skin/stmbar162.png";
  1334.     },
  1335.  
  1336.     disableBlockObserver: function() {
  1337.         Components.classes['@mozilla.org/observer-service;1'].getService(Components.interfaces.nsIObserverService).removeObserver(stmM.blockObserver, 'http-on-modify-request', false);
  1338.         gBrowser.tabContainer.removeEventListener("TabSelect", stmM.disableBlockObserver, false);
  1339.         stmM.gBlockingOn = false;
  1340.         document.getElementById("stm.statuspanel").image="chrome://supertabmode/skin/stmbar16.png";
  1341.     },
  1342.  
  1343.     toggleBlockType: function(ptype) {
  1344.         if (ptype == 9) {
  1345.             this.gPrefs.setBoolPref("block.stopOnTabSwitch", !this.gPrefs.getBoolPref("block.stopOnTabSwitch"));
  1346.             return;
  1347.         }
  1348.  
  1349.         gBrowser.selectedBrowser.stop();
  1350.         if (this.gBlockingOn && ptype == this.gPrefs.getIntPref("block.blockScope")) 
  1351.             this.disableBlockObserver();
  1352.         else{
  1353.             this.gPrefs.setIntPref("block.blockScope", ptype);
  1354.             if (!this.gBlockingOn) this.enableBlockObserver();
  1355.         }
  1356.         gBrowser.selectedBrowser.reloadWithFlags(Components.interfaces.nsIRequest.LOAD_NORMAL);
  1357.     },
  1358.  
  1359.     enableBosskey: function(penable) {
  1360.         var e = document.getElementById("k.hideFF");
  1361.         if (penable)
  1362.             e.setAttribute("disabled", false);
  1363.         else
  1364.             e.setAttribute("disabled", true);
  1365.     },
  1366.  
  1367.     hideFirefox: function() {
  1368.         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
  1369.         obj = Components.classes["@supertabmode.mozdev.org/supertabmode;1"].getService(Components.interfaces.IStmBossKey);
  1370.         var hotkey = this.gPrefs.getCharPref("bosskey.showkey");
  1371.         var list = hotkey.split("|:|")[1].split("[+]");
  1372.         var mod = "";
  1373.         list[1].indexOf("control") >= 0 ? mod = mod + "1": mod = mod + "0";
  1374.         list[1].indexOf("shift"  ) >= 0 ? mod = mod + "1": mod = mod + "0";
  1375.         list[1].indexOf("alt"    ) >= 0 ? mod = mod + "1": mod = mod + "0";
  1376.         list[1].indexOf("meta"   ) >= 0 ? mod = mod + "1": mod = mod + "0";
  1377.         var sb = document.getElementById("stm.stringmanager");
  1378.         obj.hideFirefox(mod, list[0], this.gPrefs.getBoolPref("bosskey.minimizeToTray"), 
  1379.                     sb.getString("bosskey.tooltip"), sb.getString("bosskey.restore"), sb.getString("bosskey.exit"));
  1380.     },
  1381.  
  1382.     minimizeToSysTray: function(winloaded, penable) {
  1383.         if (!winloaded && !penable) return;
  1384.         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
  1385.         obj = Components.classes["@supertabmode.mozdev.org/supertabmode;1"].getService(Components.interfaces.IStmBossKey);
  1386.         var sb = document.getElementById("stm.stringmanager");
  1387.         obj.enableSysTray(penable, sb.getString("bosskey.tooltip"), sb.getString("bosskey.restore"), sb.getString("bosskey.exit"));
  1388.     },
  1389.  
  1390. } //var end
  1391.  
  1392. window.addEventListener("load", function(e) { stmM.onLoad(); }, false);
  1393. window.addEventListener("unload", function(e) { stmM.onUnLoad(); }, false);